    //
//  ModuleTester.m
//  ModuleTesting
//
//  Created by vo loc on 8/3/11.
//  Copyright 2011 Epsilon Mobile. All rights reserved.
//

#import "ModuleTester.h"


@implementation ModuleTester
@synthesize tableView;
@synthesize toolbar;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
	self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  if( self )
  {
  	_testMode = kTestModeDemos;	
  }
  return self;
}

- (void)loadModule:(ModuleInfo*)info
{
	_moduleInfo = [info retain];
  
  _demos = [[_moduleInfo allDemos] retain];
  [self analyzeTestSuites:[_moduleInfo allTestsuits]];
  
  [self refresh];
}

- (void)updateToolbar
{
	if( _testMode == kTestModeDemos )
  {
		UIBarButtonItem* space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL];
    UIBarButtonItem* name = [[UIBarButtonItem alloc] initWithTitle:_moduleInfo.name style:UIBarButtonItemStylePlain target:nil action:NULL];
    UIBarButtonItem* close = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close:)];
    
		[self.toolbar setItems:[NSArray arrayWithObjects:space,name,space,close,nil]];
    [space release];
    [name release];
    [close release];
  }
  else if( _testMode == kTestModeUnitTests )
  {
    UIBarButtonItem* reset = [[UIBarButtonItem alloc] initWithTitle:@"Reset" style:UIBarButtonItemStyleBordered target:self action:@selector(reset:)];
    UIBarButtonItem* runAll = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:@selector(runAllTest:)];
    
		UIBarButtonItem* space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL];
    UIBarButtonItem* name = [[UIBarButtonItem alloc] initWithTitle:[_moduleInfo name] style:UIBarButtonItemStylePlain target:nil action:NULL];
    UIBarButtonItem* close = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close:)];
    
		[self.toolbar setItems:[NSArray arrayWithObjects:reset,runAll,space,name,space,close,nil]]; 
    [reset release];
    [runAll release];
    [space release];
    [close release];
    [name release];
  }
}

- (void)viewDidLoad {
  [super viewDidLoad];
  
  segmentControl.selectedSegmentIndex = 0;
  _testMode = kTestModeUnitTests;
  [self updateToolbar];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    return YES;
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc. that aren't in use.
}

- (void)releaseAllSubviews
{
	self.toolbar = nil;
  self.tableView = nil;
}

- (void)viewDidUnload {
  [super viewDidUnload];
  
  [self releaseAllSubviews];
}

- (void)dealloc {
  [self releaseAllSubviews];
  [super dealloc];
}

#pragma mark Actions
- (IBAction)testModeChanged:(id)sender
{
	if( segmentControl.selectedSegmentIndex == 0 )
  {
   	_testMode = kTestModeUnitTests;
  }
  else {
    _testMode = kTestModeDemos;
  }

  [self refresh];
  [self updateToolbar];
}
- (IBAction)runAllTest:(id)sender
{
  for( NSArray* suiteTests in _testCases )
  {
   	for( TestCaseResult* testCase in suiteTests )
    {
      [self performSelectorInBackground:@selector(runTest:) withObject:testCase];
    }
  }
}

- (IBAction)reset:(id)sender
{
  for( NSArray* suiteTests in _testCases )
  {
   	for( TestCaseResult* testCase in suiteTests )
    {
      [testCase reset];
    }
  }	
  
  [self refresh];
}

- (void)runTest:(id)sender
{
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  
  TestCaseResult* testCase = (TestCaseResult*)sender;
  [testCase runTest];
  
  [self performSelectorOnMainThread:@selector(refresh) withObject:nil waitUntilDone:NO];
  
  [pool release];
}

- (void)close:(id)sender
{
	[self dismissModalViewControllerAnimated:YES];
}

- (void)refresh
{
  [tableView reloadData];
}
- (void)analyzeTestSuites:(NSArray*)testSuites
{
  [_testSuiteName release];
  _testSuiteName = [testSuites retain];
  
  [_testCases release];
  _testCases = [[NSMutableArray alloc] init];
  
 	// extract test cases from each suite
  for( NSString* suiteName in _testSuiteName )
  {
   	Class suiteClass = objc_getClass([suiteName UTF8String]);
    
    NSMutableArray * suiteCases = [[NSMutableArray alloc] init];
    [_testCases addObject:suiteCases];
    [suiteCases release];
    
    NSArray *invocations = [suiteClass testInvocations];
    if ([invocations count]) 
    {
      NSInvocation *invocation;
      GTM_FOREACH_OBJECT(invocation, invocations) 
      {
        GTMTestCase *testCase = [[suiteClass alloc] initWithInvocation:invocation];
        
        TestCaseResult *result = [[TestCaseResult alloc] init];
        [suiteCases addObject:result];
        [result release];
        
        result.testCase = testCase;
        result.testName = NSStringFromSelector([invocation selector]);
      }
    }
  }
  
  [tableView reloadData];
}

- (void)runTestAtIndexPath:(NSIndexPath*)indexPath
{
  NSArray* suiteTests = [_testCases objectAtIndex:indexPath.section];
  TestCaseResult* testCase = [suiteTests objectAtIndex:indexPath.row];
  [self performSelectorInBackground:@selector(runTest:) withObject:testCase];
}

- (BOOL)isClassExists:(NSString*)className
{
  return ( objc_getClass([className UTF8String]) != Nil );
}

- (void)runViewControllerTest:(Class)testerClass
{
  // load view controller 
  UIViewController* viewController;
  
  NSString* nib = NSStringFromClass(testerClass);
  
  // check for nib file existence
  // - if there is no nib file, load using normal init
  // - if there is, use nib file to load
  if( [[NSBundle mainBundle] pathForResource:nib ofType:@"xib"] == nil )
  {
    viewController = [[testerClass alloc] init];
  }
  else {
    // always load with nib
    viewController = [[testerClass alloc] initWithNibName:NSStringFromClass(testerClass) bundle:nil];
  }
  
  [self presentModalViewController:viewController animated:YES];
  [viewController release];
  
  UIButton* btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 60, 30)];
  [[[UIApplication sharedApplication]keyWindow] addSubview:btn];
  [btn release];
  
  btn.backgroundColor = [UIColor blackColor];
  [btn setTitle:@"Close" forState:UIControlStateNormal];
  [btn addTarget:self action:@selector(closeChild:) forControlEvents:UIControlEventTouchUpInside];
  
  if( ![[UIApplication sharedApplication] isStatusBarHidden] )
  {
    btn.frame = CGRectMake(0, 14, 60, 30);
  }
}

- (void)closeChild:(id)sender
{
  if( [self.modalViewController respondsToSelector:@selector(saveSettings)] )
  {
   	[self.modalViewController performSelector:@selector(saveSettings)]; 
  }
  
  [self.modalViewController dismissModalViewControllerAnimated:YES];
  
  [sender removeFromSuperview];
}
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  if( _testMode == kTestModeUnitTests )
  {
  	[self runTestAtIndexPath:indexPath];
  }
  else {
    NSString* testerName = [_demos objectAtIndex:indexPath.row];
    if( ![self isClassExists:testerName] )
    {
      NSString* format = @"Class %@ not founded";
      NSString* message = [NSString stringWithFormat:format,testerName];
      UIAlertView* alert = [[UIAlertView alloc] initWithTitle:message 
                                                      message:nil 
                                                     delegate:nil 
                                            cancelButtonTitle:@"Ok" 
                                            otherButtonTitles:nil];
      [alert show];
      [alert release];
      
      return; 
    }                            
    
    Class testerClass = objc_getClass([testerName UTF8String]);
    [self runViewControllerTest:testerClass];
  }

}

#pragma mark UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
  if( _testMode == kTestModeUnitTests )
	 	return [_testCases count]; 
  else {
    return 1;
  }
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
  if( _testMode == kTestModeUnitTests )
    return [_testSuiteName objectAtIndex:section]; 
  
  return @"";
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  if( _testMode == kTestModeUnitTests )
	 	return [[_testCases objectAtIndex:section] count]; 
  else {
    return [_demos count];
  }
}

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString* CellIdentifier = @"Cell";
  
  UITableViewCell* cell = [tv dequeueReusableCellWithIdentifier:CellIdentifier];
  if( cell == nil )
  {
   	cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
  }
  
  if( _testMode == kTestModeUnitTests )
  {    
    TestCaseResult* test = [[_testCases objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    
    cell.textLabel.text = test.testName;
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%0.3f", test.runningTime];
    
    if( test.status == 1 )
    {
      cell.textLabel.textColor = [UIColor greenColor]; 
    }
    else if(test.status == 0) 
    {
      cell.textLabel.textColor = [UIColor redColor];
    }
    else {
      cell.textLabel.textColor = [UIColor blackColor];
    }
  }
  else {
    cell.textLabel.text = [_demos objectAtIndex:indexPath.row];
  }

  return cell;
}

@end
